import glfw
from OpenGL.GL import *
import numpy as np
import cv2

video_path = "/Users/xclin/Desktop/1.mp4"

# 顶点着色器代码
vertex_shader_source = """
#version 330 core
layout (location = 0) in vec3 aPos;
out vec2 TexCoord;  // 添加纹理坐标输出

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    TexCoord = (aPos.xy + 1.0) / 2.0;  // 计算纹理坐标
}
"""

# 片段着色器代码
fragment_shader_source = """
#version 330 core
in vec2 TexCoord;  // 接收纹理坐标
out vec4 FragColor;
uniform sampler2D textureSampler;  // 纹理采样器

void main()
{
    // 从纹理中采样颜色
    FragColor = texture(textureSampler, TexCoord);
}
"""

def main():
    # 初始化glfw
    if not glfw.init():
        return

    # 设置OpenGL版本号
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
    
    # 创建窗口
    window = glfw.create_window(800, 600, "OpenGL + OpenCV Example", None, None)
    if not window:
        glfw.terminate()
        return

    # 设置当前窗口上下文
    glfw.make_context_current(window)

    # 编译顶点着色器
    vertex_shader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertex_shader, vertex_shader_source)
    glCompileShader(vertex_shader)

    # 编译片段着色器
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragment_shader, fragment_shader_source)
    glCompileShader(fragment_shader)

    # 创建着色器程序
    shader_program = glCreateProgram()
    glAttachShader(shader_program, vertex_shader)
    glAttachShader(shader_program, fragment_shader)
    glLinkProgram(shader_program)
    glUseProgram(shader_program)

    # 顶点数据
    vertices = [-0.5, -0.5, 0.0,  # 左下角
                0.5, -0.5, 0.0,   # 右下角
                0.0,  0.5, 0.0]   # 顶部

    vertices = np.array(vertices, dtype=np.float32)

    # 创建顶点缓冲对象
    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW)

    # 创建顶点数组对象
    VAO = glGenVertexArrays(1)
    glBindVertexArray(VAO)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), None)
    glEnableVertexAttribArray(0)

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), ctypes.c_void_p(3 * sizeof(GLfloat)))
    glEnableVertexAttribArray(1)

    # 打开摄像头
    cap = cv2.VideoCapture(video_path)
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    # 创建纹理对象
    gl_texture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, gl_texture)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, None)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

    # glEnable(GL_BLEND)
    # glEnable(GL_DEPTH_TEST)

    while not glfw.window_should_close(window):
        glClear(GL_COLOR_BUFFER_BIT)

        # 使用着色器程序
        glUseProgram(shader_program)

        # 绑定顶点数组对象
        glBindVertexArray(VAO)

        # 绘制三角形
        glDrawArrays(GL_TRIANGLES, 0, 3)

        # 读取摄像头帧
        ret, frame = cap.read()

        # 将OpenCV图像数据传递到OpenGL纹理
        glBindTexture(GL_TEXTURE_2D, gl_texture)
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, frame)

        # 交换缓冲区并轮询事件
        glfw.swap_buffers(window)
        glfw.poll_events()

    # 清理资源
    glfw.terminate()

if __name__ == "__main__":
    main()
